/* Copyright (c) 2021 Xie Meiyi(xiemeiyi@hust.edu.cn) and OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

//
// Created by WangYunlai on 2022/07/05.
//

#include "sql/expr/tuple_cell.h"
#include "storage/common/field.h"
#include "common/log/log.h"
#include "util/comparator.h"
#include "util/util.h"

void TupleCell::to_string(std::ostream &os) const //做格式转换，需要按照输出要求，将日期类型数据，转换成合适的字符串
{
  switch (attr_type_) {
  case INTS: {
    os << *(int *)data_;
  } break;
  case FLOATS: {
    float v = *(float *)data_;
    os << double2string(v);
  } break;
  case CHARS: case TEXTS: {
    int tmp = 0;
    for (int i = 0; i < length_; i++) {
      if (data_[i] == '\0') {
        break;
      }
      os << data_[i];
      tmp ++;
    }
    printf("type is:%d\n",attr_type_);
    printf("len is :%d\n",tmp);
  } break;
  case DATES: {
    int value = *(int*)data_;
    char buf[16] = {0};
    snprintf(buf,sizeof(buf),"%04d-%02d-%02d", value/10000, (value%10000)/100, value%100); // 注意这里月份和天数，不足两位时需要填充0
    std::string date_str = std::string(buf);
    os << date_str;
  } break;
  default: {
    LOG_WARN("unsupported attr type: %d", attr_type_);
  } break;
  }
}

int TupleCell::compare(const TupleCell &other) const
{
  if (this->attr_type_ == other.attr_type_) {
    switch (this->attr_type_) {
    case INTS: return compare_int(this->data_, other.data_);
    case FLOATS: return compare_float(this->data_, other.data_);
    case TEXTS: case CHARS: return compare_string(this->data_, this->length_, other.data_, other.length_);
    case DATES: return compare_int(this->data_, other.data_); // date type is equal to int type
    default: {
      LOG_WARN("unsupported type: %d", this->attr_type_);
    }
    }
  } 
  else if (this->attr_type_ == INTS && other.attr_type_ == FLOATS) 
  {
    float this_data = *(int *)data_;
    return compare_float(&this_data, other.data_);
  } 
  else if (this->attr_type_ == FLOATS && other.attr_type_ == INTS) 
  {
    float other_data = *(int *)other.data_;
    return compare_float(data_, &other_data);
  } 
  else if (this->attr_type_ == INTS && other.attr_type_ == CHARS) 
  {
    float this_data = float(*(int *)data_);
    float other_data = (float)(std::atof(other.data_));
    return compare_float(&this_data, &other_data);
  } 
  else if (this->attr_type_ == CHARS && other.attr_type_ == INTS) 
  {
    // int this_data = (int)(std::atoi(this->data_));
    // int other_data = *(int *)other.data_;
    // return compare_int(&this_data, &other_data);

    float this_data = (float)((int)(std::atoi(this->data_)));
    float other_data = *(float *)other.data_;

    return compare_float(&this_data, &other_data);
  } 
  else if (this->attr_type_ == FLOATS && other.attr_type_ == CHARS) 
  {
    float this_data = *(float *)this->data_;
    float other_data = (float)(std::atof(other.data_));
    return compare_float(&this_data, &other_data);
  } 
  else if (this->attr_type_ == CHARS && other.attr_type_ == FLOATS) 
  {
    float this_data = (float)(std::atof(this->data_));
    printf("this data : %f\n",this_data);
    float other_data = *(float *)other.data_;
    printf("other data : %f\n",other_data);
    return compare_float(&this_data, &other_data);
  } 
  else if (this->attr_type_ == CHARS && other.attr_type_ == TEXTS) 
  {
    printf("this data: %s,this length: %d\n",this->data_,this->length_);
    printf("other data: %s,other length: %d\n",other.data_,other.length_);
    return compare_string(this->data_, this->length_, other.data_, other.length_);
  } 
  else if (this->attr_type_ == TEXTS && other.attr_type_ == CHARS) 
  {
    printf("this data: %s,this length: %d\n",this->data_,this->length_);
    printf("other data: %s,other length: %d\n",other.data_,other.length_);
    return compare_string(this->data_, this->length_, other.data_, other.length_);
  } 
  LOG_WARN("not supported");
  return -1; // TODO return rc?
}
